package org.cms.nio;

import java.io.IOException;
import java.net.StandardSocketOptions;
import java.nio.channels.NetworkChannel;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.cms.nio.bufferpool.SharedBufferPool;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
import org.cms.nio.client.NIOConnector;

/**
 * @Description: 
 * @Department:
 * @author andy.lhc
 * @date 2016年6月2日 上午10:16:18 
 */
public class NetSystem {
  // private static final Logger LOGGER = LoggerFactory.getLogger(NetSystem.class);
  private SystemConfig netConfig;
  public static final int RUNNING = 0;
  public static final int SHUTING_DOWN = -1;
  private static NetSystem INSTANCE  ;
  private final SharedBufferPool bufferPool;
  private final ConcurrentMap<Long, Connection> allConnections;
  private long netInBytes;
  private long netOutBytes;
  private NIOConnector connector;
  
  public NIOConnector getConnector() {
    return connector;
  }
  
  public void setConnector(NIOConnector connector) {
      this.connector = connector;
  }

  public static NetSystem getInstance() {
    return INSTANCE;
 }
  
  public  NetSystem(SharedBufferPool bufferPool){
    this.bufferPool = bufferPool;
     netConfig = new SystemConfig();
     this.allConnections = new ConcurrentHashMap<Long, Connection>();
     
     INSTANCE = this;
  }
  
  
  /**
   * 添加一个连接到系统中被监控
   *
   * @param c
   */
  public void addConnection(Connection c) {
      allConnections.put(c.getId(), c);
  }

  public ConcurrentMap<Long, Connection> getAllConnectios() {
      return allConnections;
  }

  /**
   * 定时执行该方法，回收部分资源。
   */
  public void checkConnections() {
      Iterator<Entry<Long, Connection>> it = allConnections.entrySet().iterator();
      while (it.hasNext()) {
          Connection c = it.next().getValue();

          // 删除空连接
          if (c == null) {
              it.remove();
              continue;
          }

          // 清理已关闭连接，否则空闲检查。
          if (c.isClosed()) {
              c.cleanup();
              it.remove();
          } else {
              c.idleCheck();
          }
      }
  }

  public void removeConnection(Connection con) {
      this.allConnections.remove(con.getId());

  }
  
  public void setSocketParams(Connection con, boolean isFrontChannel) throws IOException {
    int sorcvbuf = 0;
    int sosndbuf = 0;
    int soNoDelay = 0;
    if (isFrontChannel) {
        sorcvbuf = netConfig.getFrontsocketsorcvbuf();
        sosndbuf = netConfig.getFrontsocketsosndbuf();
        soNoDelay = netConfig.getFrontSocketNoDelay();
    } else {
        sorcvbuf = netConfig.getBacksocketsorcvbuf();
        sosndbuf = netConfig.getBacksocketsosndbuf();
        soNoDelay = netConfig.getBackSocketNoDelay();
    }
    NetworkChannel channel = con.getChannel();
    channel.setOption(StandardSocketOptions.SO_RCVBUF, sorcvbuf);
    channel.setOption(StandardSocketOptions.SO_SNDBUF, sosndbuf);
    channel.setOption(StandardSocketOptions.TCP_NODELAY, soNoDelay == 1);
    channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
    channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

    con.setMaxPacketSize(netConfig.getMaxPacketSize());
    con.setPacketHeaderSize(netConfig.getPacketHeaderSize());
  }
  
  public SharedBufferPool getBufferPool() {
    return bufferPool;
  }
  
  public int getWriteQueueSize() {
    int total = 0;
    for (Connection con : allConnections.values()) {
        total += con.getWriteQueue().size();
    }

    return total;
  }
  
  public long getNetInBytes() {
    return netInBytes;
  }
  
  public void addNetInBytes(long bytes) {
      netInBytes += bytes;
  }
  
  public long getNetOutBytes() {
      return netOutBytes;
  }
  
  public void addNetOutBytes(long bytes) {
      netOutBytes += bytes;
  }


  
  
}
